package javapop.framework.parser;

import javapop.framework.ParseContext;
import javapop.framework.ParseError;
import javapop.framework.ParseInput;
import javapop.framework.ParseResult;
import javapop.framework.Parser;

public abstract class XForm<S,D> extends Parser<D> {
	private Parser<S> source;
	private ParseError error;
	
	public XForm(Parser<S> source) {
		this.source = source;
		error = null;
	}
	
	public Parser<S> getSource() {
		return source;
	}
	
	protected void setError(String message, boolean fatal) {
		error = new ParseError(message, fatal);
	}
	
	@Override
	public String getDescription() {
		return source.getDescription();
	}
	
	public abstract D transform(ParseContext<?> ctx, S content);
	
	@Override
	public boolean isMemoized() {
		return false;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public final ParseResult<D> eval(ParseContext ctx, ParseInput input) {
		ParseResult<S> result = source.parse(ctx,input);
		if(result.isError()) {
			if(error==null) {
				return (ParseResult<D>) result.asError();
			} else {
				return (ParseResult<D>) error.cloneWithChild(result.asError());
			}
		}
		D nresult = transform(ctx, result.getResult());
		if(nresult==null) {
			if(error==null) {
				throw new IllegalStateException("Transformation error is <null>");
			}
			return (ParseResult) error;
		}
		return buildResult(nresult);
	}
}
